#include "monitor.h"
#include "common.h"

struct proc_info proc_table[100];
int index_proc_table = 0;
int first_exec_flag = 0;
int no_of_forks = 0;

int getdata(pid_t pid, long addr,char *buf, int len) //returns number of bytes read
{  
	int i, j,no_bytes;
	long ret;
	char *temp;
	i = addr;
	no_bytes = 0;
	while(1)
	{
		ret = ptrace(PTRACE_PEEKDATA,pid,i,NULL);
		if(errno != 0) //error in read
			return no_bytes;
		temp = (char*)&ret;
		j = 0;
		while(j < 4)
		{
			buf[no_bytes] = *(temp + j);
			no_bytes++;
			j++;
			if(no_bytes == len)
				return no_bytes;
		}
	}
}

int getstring(pid_t pid,long addr,char *buff,int len) //get a null terminated string
{
	int i,j,retval;
	i = addr;
	j = 0;
	while(1)
	{
		retval = getdata(pid,i,&buff[j],4);
		if(retval < 4)
			break;
		j = j + 4;
		i = i + 4;
		if(buff[j-4] == '\0' || buff[j-3] == '\0' || buff[j-2] == '\0' || buff[j-1] == '\0')
			break;
		if(j >= len)
			break;
	}
	return j;
}

int abort_syscall(int syscall, int index)
{
	pid_t pid = proc_table[index].pid;	
	int retval;

	retval = ptrace(PTRACE_POKEUSER,pid,4*EBX,NULL);
	if(retval == 0)
		proc_table[index].aborted = 1;

	return retval;
}

int change_return_value(pid_t pid, long error)
{
	int retval;
	
	retval = ptrace(PTRACE_POKEUSER,pid,4*EAX,error);

	return retval;
}

int getregs(pid_t pid, struct user_regs_struct *regs)
{
	int ret;
	ret = ptrace(PTRACE_GETREGS,pid, NULL, regs);
	return ret;
}

long getsyscall(pid_t pid)
{
	long ret;
	ret = ptrace(PTRACE_PEEKUSER,pid, 4 * ORIG_EAX,NULL);
	return ret;
}

int getsignal(pid_t pid,siginfo_t *signal_data)
{
	int ret;
	ret = ptrace(PTRACE_GETSIGINFO,pid,NULL,signal_data);
	return ret;
}

pid_t get_ppid(pid_t pid)
{
	char filename[PATH_MAX];
	FILE* fp;
	pid_t ppid = -1;
	char temp[512],temp1[512];
	sprintf(filename,"/proc/%d/status",pid);
	fp = fopen(filename,"r");
	if(!fp)
		return -1;
	while((fgets(temp,512,fp)) != NULL)
	{
		sscanf(temp,"%s %d",temp1,&ppid);	
		if(strcmp(temp1,"PPid:") == 0)
			break; 
	}
	return ppid;
}

uid_t get_uid(pid_t pid)
{
	char filename[PATH_MAX];
        FILE* fp;
        uid_t uid = -1;
	uid_t tuid;
        char temp[512],temp1[512];
        sprintf(filename,"/proc/%d/status",pid);
        fp = fopen(filename,"r");
        if(!fp)
                return -1;
        while((fgets(temp,512,fp)) != NULL)
        {
                sscanf(temp,"%s %d %d %d %d",temp1,&uid,&tuid,&tuid,&tuid);
                if(strcmp(temp1,"Uid:") == 0)
                        break;
        }                     
        return uid;
}

uid_t get_euid(pid_t pid)
{
	char filename[PATH_MAX];
        FILE* fp;
        uid_t uid = -1;
	uid_t tuid = -1;
        char temp[512],temp1[512];
        sprintf(filename,"/proc/%d/status",pid);
        fp = fopen(filename,"r");
        if(!fp)
                return -1;
        while((fgets(temp,512,fp)) != NULL)
        {
                sscanf(temp,"%s %d %d %d %d",temp1,&uid,&tuid,&uid,&uid);
                if(strcmp(temp1,"Uid:") == 0)
                        break;
        }                     
        return tuid;

}

gid_t get_gid(pid_t pid)
{
	char filename[PATH_MAX];
        FILE* fp;
        gid_t gid = -1;
	gid_t tgid;
        char temp[512],temp1[512];
        sprintf(filename,"/proc/%d/status",pid);
        fp = fopen(filename,"r");
        if(!fp)
                return -1;
        while((fgets(temp,512,fp)) != NULL)
        {
                sscanf(temp,"%s %d %d %d %d",temp1,&gid,&tgid,&tgid,&tgid);
                if(strcmp(temp1,"Gid:") == 0)
                        break;
        }                     
        return gid;
}

gid_t get_egid(pid_t pid)
{
	char filename[PATH_MAX];
        FILE* fp;
        gid_t gid = -1;
	gid_t tgid = -1;
        char temp[512],temp1[512];
        sprintf(filename,"/proc/%d/status",pid);
        fp = fopen(filename,"r");
        if(!fp)
                return -1;
        while((fgets(temp,512,fp)) != NULL)
        {
                sscanf(temp,"%s %d %d %d %d",temp1,&gid,&tgid,&gid,&gid);
                if(strcmp(temp1,"Gid:") == 0)
                        break;
        }                     
        return tgid;

}

int get_appname(pid_t pid, char *appname)
{
	char filename[PATH_MAX];
        FILE* fp;
        char temp[512],temp1[512],temp3[20];
        sprintf(filename,"/proc/%d/status",pid);
        fp = fopen(filename,"r");
        if(!fp)
                return -1;
        while((fgets(temp,512,fp)) != NULL)
        {
                sscanf(temp,"%s %s",temp3,temp1);
                if(strcmp(temp3,"Name:") == 0)
                        break;
        }         
	strcpy(appname,temp1);            
        return 0;

}

int get_cwd(pid_t pid,char *cwd)
{
	int ret;
	char str[100];
	sprintf(str,"/proc/%d/cwd",pid);
	ret = readlink(str,cwd,PATH_MAX);
	if(ret)
		cwd[ret] = '\0';
	
	return ret;
}

void absolute_path(char *orig, char *dest,pid_t pid)
{
	int ret;
	char cwd[PATH_MAX];
	if(orig[0] != '/')
	{
		get_cwd(pid,cwd);
		strcpy(dest,cwd);
		strcat(dest,"/");
		strcat(dest,orig);
	}
	else
	{
		strcpy(dest,orig);
	}
	//remove trailing /
	ret = strlen(dest);
	if(dest[ret - 1] == '/')
		dest[ret - 1] = '\0';
}	

void handle_open(pid_t pid)
{
	int retval,ret;
	struct user_regs_struct regs;
	char buff[PATH_MAX];
	char appname[512];

	retval = lookup_proc(pid);
	
	ret = getregs(pid,&regs); 
	if(regs.eax == -38)
		proc_table[retval].entry_flag == 0;
	else
		proc_table[retval].entry_flag == 1;
	
	if(proc_table[retval].entry_flag == 0)
	{
		struct syscall_args args;

		proc_table[retval].entry_flag = 1;
		proc_table[retval].syscall_no = __NR_open;
		ret = getstring(pid,regs.ebx,buff,PATH_MAX);
		absolute_path(buff,args.path,pid);
		args.flags = regs.ecx;
		get_appname(pid,appname);
		ret = main_controller(__NR_open,appname,args,pid);
		if(ret < 0)
		{
			abort_syscall(__NR_open,retval);
		}
		printf("open called with the parameter######## %s %d\n",buff,regs.ecx);
	}
	else
	{
		proc_table[retval].entry_flag = 0;
		proc_table[retval].syscall_no = 0;
		if(proc_table[retval].aborted == 1)
		{
			change_return_value(pid,-EACCES);
			proc_table[retval].aborted = 0;
		}
	}

}

void handle_creat(pid_t pid)
{
	int retval,ret;
	struct user_regs_struct regs;
	char buff[PATH_MAX],appname[512];
	struct syscall_args args;
	
	retval = lookup_proc(pid);
	
	ret = getregs(pid,&regs); 
	if(regs.eax == -38)
		proc_table[retval].entry_flag == 0;
	else
		proc_table[retval].entry_flag == 1;
	
	if(proc_table[retval].entry_flag == 0)
	{
		proc_table[retval].entry_flag = 1;
		proc_table[retval].syscall_no = __NR_creat;
		ret = getstring(pid,regs.ebx,buff,PATH_MAX);
		absolute_path(buff,args.path,pid);
		args.flags = regs.ecx;
		get_appname(pid,appname);
		ret = main_controller(__NR_creat,appname,args,pid);
		if(ret < 0)
		{
			abort_syscall(__NR_creat,retval);
		}
		printf("create called with the parameter######## %s\n",buff);
		
	}
	else
	{
		proc_table[retval].entry_flag = 0;
		proc_table[retval].syscall_no = 0;
		if(proc_table[retval].aborted == 1)
		{
			change_return_value(pid,-EACCES);
			proc_table[retval].aborted = 0;
		}
	}

}

void handle_mkdir(pid_t pid)
{
	int retval,ret;
	struct user_regs_struct regs;
	char buff[PATH_MAX];
	struct syscall_args args;
	char appname[512];
	
	retval = lookup_proc(pid);
	
	ret = getregs(pid,&regs); 
	if(regs.eax == -38)
		proc_table[retval].entry_flag == 0;
	else
		proc_table[retval].entry_flag == 1;
	
	if(proc_table[retval].entry_flag == 0)
	{
		proc_table[retval].entry_flag = 1;
		proc_table[retval].syscall_no = __NR_mkdir;
		ret = getstring(pid,regs.ebx,buff,PATH_MAX);
		absolute_path(buff,args.path,pid);
		args.flags = regs.ecx;
		get_appname(pid,appname);
		ret = main_controller(__NR_mkdir,appname,args,pid);
		if(ret < 0)
		{
			abort_syscall(__NR_mkdir,retval);
		}
		printf("mkdir called with the parameter######## %s\n",buff);
	}
	else
	{
		proc_table[retval].entry_flag = 0;
		proc_table[retval].syscall_no = 0;
		if(proc_table[retval].aborted == 1)
		{
			change_return_value(pid,-EACCES);
			proc_table[retval].aborted = 0;
		}
	}
}

void handle_symlink(pid_t pid)
{
	int retval,ret;
	struct user_regs_struct regs;
	char path1[PATH_MAX],path2[PATH_MAX];
	struct syscall_args args;
	char appname[512];
	
	retval = lookup_proc(pid);
	
	ret = getregs(pid,&regs); 
	if(regs.eax == -38)
		proc_table[retval].entry_flag == 0;
	else
		proc_table[retval].entry_flag == 1;
	
	if(proc_table[retval].entry_flag == 0)
	{
		proc_table[retval].entry_flag = 1;
		proc_table[retval].syscall_no = __NR_symlink;
		ret = getstring(pid,regs.ebx,path1,PATH_MAX);
		ret = getstring(pid,regs.ecx,path2,PATH_MAX);
		absolute_path(path1,args.target,pid);
		absolute_path(path2,args.path,pid);
		ret = main_controller(__NR_symlink,appname,args,pid);
		if(ret < 0)
		{
			abort_syscall(__NR_symlink,retval);
		}

		printf("symlink called with the parameter######## %s %s \n",path1,path2);
	}
	else
	{
		proc_table[retval].entry_flag = 0;
		proc_table[retval].syscall_no = 0;
		if(proc_table[retval].aborted == 1)
		{
			change_return_value(pid,-EACCES);
			proc_table[retval].aborted = 0;
		}
	}

}

void handle_link(pid_t pid)
{
	int retval,ret;
	struct user_regs_struct regs;
	char path1[PATH_MAX],path2[PATH_MAX];
	struct syscall_args args;
	char appname[512];

	retval = lookup_proc(pid);
	
	ret = getregs(pid,&regs); 
	if(regs.eax == -38)
		proc_table[retval].entry_flag == 0;
	else
		proc_table[retval].entry_flag == 1;
	
	if(proc_table[retval].entry_flag == 0)
	{
		proc_table[retval].entry_flag = 1;
		proc_table[retval].syscall_no = __NR_link;
		ret = getstring(pid,regs.ebx,path1,PATH_MAX);
		ret = getstring(pid,regs.ecx,path2,PATH_MAX);
		absolute_path(path1,args.target,pid);
		absolute_path(path2,args.path,pid);
		ret = main_controller(__NR_link,appname,args,pid);
		if(ret < 0)
		{
			abort_syscall(__NR_link,retval);
		}
		printf("link called with the parameter######## %s %s \n",path1,path2);
	}
	else
	{
		proc_table[retval].entry_flag = 0;
		proc_table[retval].syscall_no = 0;
		if(proc_table[retval].aborted == 1)
		{
			change_return_value(pid,-EACCES);
			proc_table[retval].aborted = 0;
		}
	}

}

void handle_rename(pid_t pid)
{
	int retval,ret;
	struct user_regs_struct regs;
	char path1[PATH_MAX],path2[PATH_MAX];
	struct syscall_args args;
	char appname[512];

	retval = lookup_proc(pid);
	
	ret = getregs(pid,&regs); 
	if(regs.eax == -38)
		proc_table[retval].entry_flag == 0;
	else
		proc_table[retval].entry_flag == 1;
	
	if(proc_table[retval].entry_flag == 0)
	{
		proc_table[retval].entry_flag = 1;
		proc_table[retval].syscall_no = __NR_rename;
		ret = getstring(pid,regs.ebx,path1,PATH_MAX);
		ret = getstring(pid,regs.ecx,path2,PATH_MAX);
		absolute_path(path1,args.target,pid);
		absolute_path(path2,args.path,pid);
		ret = main_controller(__NR_rename,appname,args,pid);
		if(ret < 0)
		{
			abort_syscall(__NR_rename,retval);
		}
		printf("rename called with the parameter######## %s %s \n",path1,path2);
	}
	else
	{
		proc_table[retval].entry_flag = 0;
		proc_table[retval].syscall_no = 0;
		if(proc_table[retval].aborted == 1)
		{
			change_return_value(pid,-EACCES);
			proc_table[retval].aborted = 0;
		}
	}

}

void handle_unlink(pid_t pid)
{
	int retval,ret;
	struct user_regs_struct regs;
	char path1[PATH_MAX];
	struct syscall_args args;
	char appname[512];

	retval = lookup_proc(pid);
	
	ret = getregs(pid,&regs); 
	if(regs.eax == -38)
		proc_table[retval].entry_flag == 0;
	else
		proc_table[retval].entry_flag == 1;
	
	if(proc_table[retval].entry_flag == 0)
	{
		proc_table[retval].entry_flag = 1;
		proc_table[retval].syscall_no = __NR_unlink;
		ret = getstring(pid,regs.ebx,path1,PATH_MAX);
		absolute_path(path1,args.path,pid);
		ret = main_controller(__NR_unlink,appname,args,pid);
		if(ret < 0)
		{
			abort_syscall(__NR_unlink,retval);
		}
		printf("unlink called with the parameter######## %s \n",path1);
	}
	else
	{
		proc_table[retval].entry_flag = 0;
		proc_table[retval].syscall_no = 0;
		if(proc_table[retval].aborted == 1)
		{
			change_return_value(pid,-EACCES);
			proc_table[retval].aborted = 0;
		}
	}
}

void handle_chmod(pid_t pid)
{
	int retval,ret;
	struct user_regs_struct regs;
	char path1[PATH_MAX];
	struct syscall_args args;
	char appname[512];

	retval = lookup_proc(pid);
	
	ret = getregs(pid,&regs); 
	if(regs.eax == -38)
		proc_table[retval].entry_flag == 0;
	else
		proc_table[retval].entry_flag == 1;
	
	if(proc_table[retval].entry_flag == 0)
	{
		proc_table[retval].entry_flag = 1;
		proc_table[retval].syscall_no = __NR_chmod;
		ret = getstring(pid,regs.ebx,path1,PATH_MAX);
		absolute_path(path1,args.path,pid);
		args.flags = regs.ecx;
		ret = main_controller(__NR_chmod,appname,args,pid);
		if(ret < 0)
		{
			abort_syscall(__NR_chmod,retval);
		}
		printf("chmod called with the parameter######## %s \n",path1);
	}
	else
	{
		proc_table[retval].entry_flag = 0;
		proc_table[retval].syscall_no = 0;
		if(proc_table[retval].aborted == 1)
		{
			change_return_value(pid,-EACCES);
			proc_table[retval].aborted = 0;
		}
	}
}

void handle_chown(pid_t pid)
{
	int retval,ret;
	struct user_regs_struct regs;
	char path1[PATH_MAX];
	struct syscall_args args;
	char appname[512];

	retval = lookup_proc(pid);
	
	ret = getregs(pid,&regs); 
	if(regs.eax == -38)
		proc_table[retval].entry_flag == 0;
	else
		proc_table[retval].entry_flag == 1;
	
	if(proc_table[retval].entry_flag == 0)
	{
		proc_table[retval].entry_flag = 1;
		proc_table[retval].syscall_no = __NR_chown;
		ret = getstring(pid,regs.ebx,path1,PATH_MAX);
		args.flags = regs.ecx;
		args.flags1 = regs.edx;
		absolute_path(path1,args.path,pid);
		ret = main_controller(__NR_chown,appname,args,pid);
		if(ret < 0)
		{
			abort_syscall(__NR_chown,retval);
		}
		printf("chown called with the parameter######## %s \n",path1);
	}
	else
	{
		proc_table[retval].entry_flag = 0;
		proc_table[retval].syscall_no = 0;
		if(proc_table[retval].aborted == 1)
		{
			change_return_value(pid,-EACCES);
			proc_table[retval].aborted = 0;
		}
	}
}

void handle_rmdir(pid_t pid)
{
	int retval,ret;
	struct user_regs_struct regs;
	char path1[PATH_MAX];
	struct syscall_args args;
	char appname[512];
	
	retval = lookup_proc(pid);
	
	ret = getregs(pid,&regs); 
	if(regs.eax == -38)
		proc_table[retval].entry_flag == 0;
	else
		proc_table[retval].entry_flag == 1;
	
	if(proc_table[retval].entry_flag == 0)
	{
		proc_table[retval].entry_flag = 1;
		proc_table[retval].syscall_no = __NR_rmdir;
		retval = getstring(pid,regs.ebx,path1,PATH_MAX);
		absolute_path(path1,args.path,pid);
		ret = main_controller(__NR_rmdir,appname,args,pid);
		if(ret < 0)
		{
			abort_syscall(__NR_rmdir,retval);
		}
		printf("rmdir called with the parameter######## %s \n",path1);
	}
	else
	{
		proc_table[retval].entry_flag = 0;
		proc_table[retval].syscall_no = 0;
		if(proc_table[retval].aborted == 1)
		{
			change_return_value(pid,-EACCES);
			proc_table[retval].aborted = 0;
		}
	}
}

void handle_stat64(pid_t pid)
{
	int retval,ret;
	struct user_regs_struct regs;
	struct stat buff;
	char path1[PATH_MAX]; 
	
	retval = lookup_proc(pid);
	
	ret = getregs(pid,&regs); 
	if(regs.eax == -38)
		proc_table[retval].entry_flag == 0;
	else
		proc_table[retval].entry_flag == 1;
	
	if(proc_table[retval].entry_flag == 0)
	{
		proc_table[retval].entry_flag = 1;
		proc_table[retval].syscall_no = __NR_stat64;
	}
	else
	{
		proc_table[retval].entry_flag = 0;
		proc_table[retval].syscall_no = 0;
		retval = getdata(pid,regs.ecx,(char*)&buff,sizeof(struct stat));
		retval = getstring(pid,regs.ebx,path1,PATH_MAX);
	}
}

void handle_exec(pid_t pid)
{
	int retval,ret;
	struct user_regs_struct regs;
	char path1[PATH_MAX]; 
	struct syscall_args args;
	char appname[512];

	retval = lookup_proc(pid);
	
	ret = getregs(pid,&regs); 
	if(regs.eax == -38)
		proc_table[retval].entry_flag == 0;
	else
		proc_table[retval].entry_flag == 1;
	
	if(retval >= 0)
	{
		if(proc_table[retval].entry_flag == 0)
		{
			proc_table[retval].entry_flag = 1;
			proc_table[retval].syscall_no = __NR_execve;
			ret = getstring(pid,regs.ebx,path1,PATH_MAX);
			
			absolute_path(path1,args.path,pid);
			get_appname(pid,appname);
			ret = main_controller(__NR_execve,appname,args,pid);
			if(ret < 0)
			{
				abort_syscall(__NR_execve,retval);
			}

			printf("exec called with the parameter entryyy ######## %s %d\n",path1,regs.eax);
		}
		else if(proc_table[retval].entry_flag == 1)
		{
			proc_table[retval].entry_flag++;
			if(proc_table[retval].aborted == 1)
			{
				change_return_value(pid,-EACCES);
				proc_table[retval].aborted = 0;
			}
		}
		else if(proc_table[retval].entry_flag == 2)
		{
			proc_table[retval].entry_flag = 0;
			proc_table[retval].syscall_no = 0;
		}
	}

}

void handle_socketcall(pid_t pid)
{
	int retval,ret;
	struct user_regs_struct regs;
	char appname[512];
	struct syscall_args args;
	
	retval = lookup_proc(pid);
	
	ret = getregs(pid,&regs); 
	if(regs.eax == -38)
		proc_table[retval].entry_flag == 0;
	else
		proc_table[retval].entry_flag == 1;
	
	if(retval >= 0)
	{
		if(proc_table[retval].entry_flag == 0)
		{
			proc_table[retval].entry_flag = 1;
			proc_table[retval].syscall_no = __NR_socketcall;
			printf("socketcall called with the parameter######## %d\n",regs.ebx);
			switch(regs.ebx)
			{
				case SYS_SOCKET :	
				case SYS_BIND : 
				case SYS_CONNECT :     
				case SYS_LISTEN :     
				case SYS_ACCEPT :   
				case SYS_GETSOCKNAME : 
				case SYS_GETPEERNAME :
				case SYS_SOCKETPAIR :
				case SYS_SEND :     
				case SYS_RECV :    
				case SYS_SENDTO : 
				case SYS_RECVFROM :
				case SYS_SHUTDOWN :
				case SYS_SETSOCKOPT :
				case SYS_GETSOCKOPT :
				case SYS_SENDMSG : 
				case SYS_RECVMSG : break;
			}
			get_appname(pid,appname);
                        ret = main_controller(__NR_socketcall,appname,args,pid);
			if(ret < 0)
                        {
                                abort_syscall(__NR_socketcall,retval);
                        }
		}
		else
		{
			proc_table[retval].entry_flag = 0;
			proc_table[retval].syscall_no = 0;
			if(proc_table[retval].aborted == 1)
                	{
                        	change_return_value(pid,-EACCES);
                        	proc_table[retval].aborted = 0;
                	}
		}
	}

}

void handle_other_call(pid_t pid,int syscall_no)
{
	int retval,ret;
	struct syscall_args args;
	char appname[512];
	struct user_regs_struct regs;

	retval = lookup_proc(pid);
	
	ret = getregs(pid,&regs); 
	if(regs.eax == -38)
		proc_table[retval].entry_flag == 0;
	else
		proc_table[retval].entry_flag == 1;
	
	if(proc_table[retval].entry_flag == 0)
	{
		proc_table[retval].entry_flag = 1;
		proc_table[retval].syscall_no = syscall_no;
		get_appname(pid,appname);
		ret = main_controller(syscall_no,appname,args,pid);
		if(ret < 0)
		{
			//abort_syscall(syscall_no,retval);
		}
	}
	else
	{
		proc_table[retval].entry_flag = 0;
		proc_table[retval].syscall_no = 0;
		if(proc_table[retval].aborted == 1)
		{
			//change_return_value(pid,-EACCES);
			proc_table[retval].aborted = 0;
		}
	}
}


int add_proc(pid_t pid,pid_t ppid,int syscall_no,int entry_flag)
{
	proc_table[index_proc_table].pid = pid;
	proc_table[index_proc_table].ppid = ppid;
	proc_table[index_proc_table].syscall_no = syscall_no;
	proc_table[index_proc_table].syscall_no = entry_flag;
	proc_table[index_proc_table].aborted = 0;
	index_proc_table++;
	return 0;
}

int lookup_proc(pid_t pid)
{
	int pos = -1,i;
	for(i = 0; i < index_proc_table ; i++)
	{
		if(proc_table[i].pid == pid)
		{	
			pos = i; 
			break;
		}
	}
	return pos;
}

int remove_proc(pid_t pid)
{
	int i,pos;
	pos = lookup_proc(pid);
	if(pos < 0)
		return -1;
	for(i = pos; i < index_proc_table - 1 ; i++)
               	proc_table[i] = proc_table[i+1];
	index_proc_table--;
	return 0;
}

void wait_for_call()
{
	pid_t pid;
	int status;
	long syscall;
	siginfo_t signal_data;
	int retval,count = 0;
	
	long event;	

	while(1)
	{
		pid = wait4(-1,&status,__WALL,0);
		if(pid < 0)
			break;
		if(WIFEXITED(status))	
		{
			printf("removing the process %ld \n",pid);
			retval = remove_proc(pid);
			if(index_proc_table == 0 && no_of_forks == 0)
				break;
		}
		else
		{
			printf("------pid = %ld---%d------\n",pid,count);		
			syscall = getsyscall(pid);
			retval = getsignal(pid,&signal_data);
			
			printf("system call number = %ld  signal number = %d\n",syscall,signal_data.si_signo);
			
			if(first_exec_flag == 0 && syscall == __NR_execve)
			{
				retval = ptrace(PTRACE_SETOPTIONS, pid, NULL, PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE);
				first_exec_flag = 1;
			}
			else if(first_exec_flag == 1 && syscall == __NR_execve)
			{
				ptrace(PTRACE_GETEVENTMSG,pid,NULL,&event);
				printf(" event  %ld \n",event);
				handle_exec(pid);
			}
			else if(signal_data.si_signo == SIGSTOP && (syscall == __NR_fork || syscall == __NR_clone || syscall == __NR_vfork))
			{
				printf("-----CHILD-------- %d\n",pid);
				//this is the child process after a fork
				retval = lookup_proc(pid);
				if(retval < 0)
				{	
					no_of_forks--;
					retval = add_proc(pid,0,0,0);
					retval = ptrace(PTRACE_SETOPTIONS,pid,NULL,PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE);
				}
			}
			else if(signal_data.si_signo == SIGTRAP && (syscall == __NR_fork || syscall == __NR_clone || syscall == __NR_vfork))
			{
				printf("-----PARENT-------- %d\n",pid);
				//this is the parent process after a fork
				retval = lookup_proc(pid);
				if(retval < 0)
				{	
					proc_table[retval].syscall_no = syscall;
					if(proc_table[retval].entry_flag == 0)
					{	
						proc_table[retval].entry_flag ++;
						no_of_forks++;
					}
					else if(proc_table[retval].entry_flag == 1)
					{	
						proc_table[retval].entry_flag ++;
					}
					else if(proc_table[retval].entry_flag == 2)				
					{
						proc_table[retval].entry_flag = 0;
						proc_table[retval].syscall_no = 0;	
					}
				}
			}
		
			else 
			{
			
				switch(syscall)
				{
					case __NR_open : handle_open(pid);
							 break;
					case __NR_creat : handle_creat(pid);
							  break;
					case __NR_mkdir : handle_mkdir(pid);
							  break;
					case __NR_symlink : handle_symlink(pid);
							    break;
					case __NR_link : handle_link(pid);
							 break;
					case __NR_rename : handle_rename(pid);
							   break;
					case __NR_unlink : handle_unlink(pid);
							   break;
					case __NR_chmod : handle_chmod(pid);
							  break;
					case __NR_chown : handle_chown(pid);
							  break;
					case __NR_rmdir : handle_rmdir(pid);
							  break;
					case __NR_stat64 : handle_stat64(pid);
							   break;
					case __NR_socketcall : handle_socketcall(pid);
							       break;
					/*default    : handle_other_call(pid,syscall);
							  break;*/
				}
			}
			ptrace(PTRACE_SYSCALL,pid,NULL,NULL);
			printf("--------%d----\n",count);
			count++;
		}

	}

}

void start_tracing(const char *path, char **argv)
{
	pid_t pid;
	int ret;
	pid = fork();
	if(pid == 0)
	{
		ptrace(PTRACE_TRACEME, 0,NULL, NULL);
		ret = execv(path,argv);
	}
	else
	{
		add_proc(pid,0,0,0);
		wait_for_call();
	}

}

int main(int argc, char **argv)
{
	char path[15];
	start_tracing("testapp1",argv);
	//printf("%s \n",argv[2]);
        //execv(argv[1],&(argv[2]));
	return 0;
}
